package com.bunker.client;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

public class GameContainer implements EntryPoint {
	
	// ArrayList
	private ArrayList<Entity> CurrentLevel;
	private ArrayList<ArrayList<Entity>> Levels;
	private ArrayList<Entity> removeList;
	
	// canvas
	private Canvas canvas = null;
	private Context2d context;
	
	private static final int canvasWidth = 800;
	private static final int canvasHeight = 600;
	
	// event
	public int mouseButton;
	public Point mousePosition;
	
	// timer
	private Timer gameTimer;
	private final int FPS = 15;
	private boolean isPause;
	
	public void onModuleLoad() {
		
		// initialization
		GameInit();
		
		// run game loop
		
		gameTimer = new Timer() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				GameLoop();
			}
			
		};
		
		loadContent();
		
		gameTimer.scheduleRepeating(FPS);
	}
	
	private void GameInit() {
		
		// create a canvas if the web supported it
		canvas = Canvas.createIfSupported();
		if(canvas == null) {
			RootPanel.get().add(new Label("Your browser does not support canvas!"));
		}
		
		mousePosition = new Point();
		
		canvas.addMouseDownHandler(new MouseDownHandler() {
			@Override
			public void onMouseDown(MouseDownEvent event) {
				// TODO Auto-generated method stub
				/*Window.alert(event.getNativeButton()+"");*/
				/*
				if(event.getNativeButton() == Event.BUTTON_LEFT) {
					GWT.log("Fire");
				}
				*/
				event.stopPropagation();
				event.preventDefault();
				if(event != null)
					mouseButton = event.getNativeButton();
				
				mousePosition.x = event.getX();
				mousePosition.y = event.getY();
				
				//GWT.log("position: (" + mousePosition.x + "," + mousePosition.y + ")");
				
				if(event.getNativeButton() == Event.BUTTON_MIDDLE) {
					if(!isPause) {
						pauseGame();
						isPause = !isPause;
					}
					else {
						resumeGame();
						isPause = !isPause;
					}
				}
			}
		});
		
		canvas.setStyleName("mainCanvas");
		
		canvas.setWidth(canvasWidth + "px");
		canvas.setCoordinateSpaceWidth(canvasWidth);
		
		canvas.setHeight(canvasHeight + "px");
		canvas.setCoordinateSpaceHeight(canvasHeight);
		
		RootPanel.get().add(canvas);
		context = canvas.getContext2d();
		
		CurrentLevel = new ArrayList<Entity>();
		Levels = new ArrayList<ArrayList<Entity>>();
		removeList = new ArrayList<Entity>();
		
		isPause = false;
	}
	
	private void loadContent() {
		
		// level 1
		ArrayList<Entity> level1 = new ArrayList<Entity>();
		
		// player
		Entity Player = new Entity("Player");
		Player.setPosition(new Point(497, 504));
		Player.setWidth(113);
		Player.setHeight(94);
		Player.setHotspot(new Point(553,490));
		Player.AddComponent(new FireComponent("PlayerFire", 5));
		Player.AddComponent(new HPComponent("playerHP", 10));
		Player.AddComponent(new MoneyComponent("playerMoney", 0));
		Player.AddComponent(new KillNumComponent("playerKill", 0));
		Player.AddRendercomponent(new HPRenderComponent("HPRenderComponent", "playerHP", new Point(30, 50)));
		Player.AddRendercomponent(new MoneyRenderComponent("HPRenderComponent", "playerMoney", new Point(30, 100)));
		Player.AddRendercomponent(new KillRenderComponent("HPRenderComponent", "playerKill", new Point(30, 150)));
		
		// background
		ImageElement BackgroundImg = (ImageElement) new Image("img//sprite4-default-000.png").getElement().cast();
		Entity background = new Entity("Background");
		background.setPosition(new Point());
		background.setWidth(0);
		background.setHeight(0);
		SingleImageRenderComponent bgImg = new SingleImageRenderComponent("bacground", BackgroundImg);
		background.AddRendercomponent(bgImg);
		
		// Bomb build
		ImageElement BombButtonImg = (ImageElement) new Image("img//bomb.png").getElement().cast();
		Entity BombButton = new Entity("BombButton");
		BombButton.setPosition(new Point(20, 500));
		background.setWidth(0);
		background.setHeight(0);
		SingleImageRenderComponent BombRenderComponent = new SingleImageRenderComponent("BombButtonRender", BombButtonImg);
		BombButton.AddRendercomponent(BombRenderComponent);
		
		// Spike build
		ImageElement SpikeButtonImg = (ImageElement) new Image("img//spike.png").getElement().cast();
		Entity SpikeButton = new Entity("SpikeButton");
		SpikeButton.setPosition(new Point(111, 500));
		background.setWidth(0);
		background.setHeight(0);
		SingleImageRenderComponent SpikeRenderComponent = new SingleImageRenderComponent("SpikeButtonImg", SpikeButtonImg);
		SpikeButton.AddRendercomponent(SpikeRenderComponent);
		
		// Heal build
		ImageElement HealButtonImg = (ImageElement) new Image("img//heal.png").getElement().cast();
		Entity HealButton = new Entity("HealButton");
		HealButton.setPosition(new Point(202, 500));
		background.setWidth(0);
		background.setHeight(0);
		SingleImageRenderComponent HealRenderComponent = new SingleImageRenderComponent("HealButtonImg", HealButtonImg);
		HealButton.AddRendercomponent(HealRenderComponent);
		
		// Soldier Generator
		Entity Generator = new Entity("SoldierGenerator");
		Generator.AddComponent(new SoldierGeneratorComponent("SoldierGenerator"));
		
		level1.add(background);
		level1.add(BombButton);
		level1.add(SpikeButton);
		level1.add(HealButton);
		level1.add(Player);
		level1.add(Generator);
		
		Levels.add(level1);
		
		setCurrentLevel(0);
	}
	
	private void update() {
		
		// updating list
		for(int i = 0; i < CurrentLevel.size(); i++) {
			for(int j = 0; j < CurrentLevel.get(i).getComponentList().size(); j++) {
				CurrentLevel.get(i).getComponentList().get(j).update(this);
			}
		}
		
	}
	
	private void render() {
		context.save();
		
		for(int i = 0; i < CurrentLevel.size(); i++) {
			for(int j = 0; j < CurrentLevel.get(i).getRenderComponentList().size(); j++) {
				CurrentLevel.get(i).getRenderComponentList().get(j).render(this, canvas);
			}
		}
		
		context.restore();
	}
	
	private void cleanUp() {
		
		//GWT.log("Size before remove:" + CurrentLevel.size());
		
		for(int i = 0; i < CurrentLevel.size(); i++) {
			if(CurrentLevel.get(i).isToRemove()) {
				removeList.add(CurrentLevel.get(i));
				/*
				GWT.log("remove object: " + CurrentLevel.get(i).getId());
				GWT.log("Size of removeList:" + removeList.size());
				*/
			}
		}
		
		
		
		//GWT.log("Size of removeList:" + removeList.size());
		CurrentLevel.removeAll(removeList);
		//GWT.log("Size after remove:" + CurrentLevel.size());
		
		removeList.clear();
	}
	
	private void GameLoop() {
		update();
		render();
		cleanUp();
	}
	
	public void setCurrentLevel(int i) {
		CurrentLevel = Levels.get(i);
	}
	
	public void insertToCurrentLevel(int index, Entity e) {
		CurrentLevel.add(index, e);
	}
	
	public void addToCurrentLevel(Entity e) {
		CurrentLevel.add(e);
	}
	
	public ArrayList<Entity> getCurrentLevelList() {
		return CurrentLevel;
	}
	
	public void addToRemoveList(Entity e) {
		removeList.add(e);
	}
	
	public void pauseGame() {
		this.gameTimer.cancel();
	}
	
	public void resumeGame() {
		this.gameTimer.scheduleRepeating(FPS);
		
	}
	
	public long getMilli() {
		Date date = new Date();
		return date.getTime();
	}
}
